package com.mxpio.erp.inventory.service.impl;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.mxpio.erp.common.enums.CommonEnums;
import com.mxpio.erp.common.enums.ItemEnums;
import com.mxpio.erp.common.inventory.entity.InvFlow;
import com.mxpio.erp.common.inventory.entity.Lot;
import com.mxpio.erp.common.inventory.entity.WarehouseOrder;
import com.mxpio.erp.common.inventory.service.LotService;
import com.mxpio.erp.common.jpa.entity.BizNoticeType;
import com.mxpio.erp.common.jpa.model.Notice;
import com.mxpio.erp.common.jpa.model.Order;
import com.mxpio.erp.common.quality.entity.InQualityOrder;
import com.mxpio.erp.common.technology.entity.Item;
import com.mxpio.erp.common.technology.entity.ItemPropKey;
import com.mxpio.erp.common.technology.entity.ItemStoreProp;
import com.mxpio.erp.common.vo.InvFlowSummaryVo;
import com.mxpio.erp.common.vo.OrderExcuteLineVo;
import com.mxpio.erp.common.workshop.entity.ManufactureOrder;
import com.mxpioframework.jpa.JpaUtil;
import com.mxpioframework.jpa.lin.Linq;
import com.mxpioframework.system.service.SnRuleService;
import com.mxpioframework.system.service.impl.BaseServiceImpl;

@Service
public class LotServiceImpl extends BaseServiceImpl<Lot> implements LotService {
	
	@Autowired
	private SnRuleService snRuleService;
	
	@Override
	@Transactional(readOnly = false)
	public String getNewLot(Order order, OrderExcuteLineVo vo) {
		ItemPropKey key = new ItemPropKey();
		key.setCode(vo.getItemCode());
		key.setPropType(ItemEnums.PropType.ITEM.getTypeCode());
		ItemStoreProp prop = JpaUtil.getOne(ItemStoreProp.class, key);
		if(CommonEnums.YesNo.YES.getCode().equals(prop.getBatchControl())) {
			Lot lot = new Lot();
			String lotNoEx = "";
			if(order instanceof WarehouseOrder) {
				lotNoEx = ((WarehouseOrder) order).getOriginBizNo() + "-" + vo.getBizOrderlineNo() + "####";
			}else if(order instanceof ManufactureOrder){
				lotNoEx = order.getBizNo() + "-" + "####";
			}
			lot.setLotNo(snRuleService.execute(lotNoEx, null).toString());
			lot.setLotStatus("1");
			JpaUtil.save(lot);
			return lot.getLotNo();
		}else {
			return "none";
		}
	}
	
	@Override
	@Transactional(readOnly = false)
	public String getNewLot(Notice notice, OrderExcuteLineVo vo, Map<String, BizNoticeType> typesMap) {
		
		ItemPropKey key = new ItemPropKey();
		key.setCode(vo.getItemCode());
		key.setPropType(ItemEnums.PropType.ITEM.getTypeCode());
		ItemStoreProp prop = JpaUtil.getOne(ItemStoreProp.class, key);
		if(CommonEnums.YesNo.YES.getCode().equals(prop==null?CommonEnums.YesNo.YES.getCode():prop.getBatchControl())) {
			Lot lot = new Lot();
			String lotNo = null;
			if(notice instanceof InQualityOrder){
				lotNo = notice.getBizOrderNo()+ "-" + vo.getNoticeLineNo();
			}else{
				BizNoticeType bizNoticeType = typesMap.get((new InQualityOrder()).getTypeCode());
				StringBuffer expression = new StringBuffer(bizNoticeType.getTypePrefix());
				for(int i=0 ;i < bizNoticeType.getTypeSize(); i++){
					expression.append("#");
				}
				//lotNo = snRuleService.execute(expression.toString(), null).toString()+ "-" + vo.getNoticeLineNo();
				if (StringUtils.isBlank(notice.getTempInQualityOrderNo())){
					notice.setTempInQualityOrderNo(snRuleService.execute(expression.toString(), null).toString());
				}
				lotNo = notice.getTempInQualityOrderNo()+ "-" + vo.getNoticeLineNo();//弃用上边注释部分代码的原因是：生成的批次号不规范（Q0100000001-1,Q0100000002-2而非Q0100000001-1，Q0100000001-2）
			}
			lot.setLotNo(lotNo);
			lot.setLotStatus("1");
			JpaUtil.save(lot);
			return lotNo;
		}else {
			return "none";
		}
	}

	@Override
	@Transactional(readOnly = true)
	public BigDecimal getStock(String whCode, String itemCode, String lotNo) {
		String sqlIn = "SELECT SUM(QUANTITY_) AS QUANTITY_ FROM MB_ERP_INV_FLOW WHERE ACCESS_TYPE_ = 'in' AND LOT_NO_ = '" + lotNo 
				+ "' AND WH_CODE_ = '" + whCode + "' AND ITEM_CODE_ = '" + itemCode + "'";
		BigDecimal sumIn = (BigDecimal) JpaUtil.nativeQuery(sqlIn).getSingleResult();
		String sqlOut = "SELECT SUM(QUANTITY_) AS QUANTITY_ FROM MB_ERP_INV_FLOW WHERE ACCESS_TYPE_ = 'out' AND LOT_NO_ = '" + lotNo 
				+ "' AND WH_CODE_ = '" + whCode + "' AND ITEM_CODE_ = '" + itemCode + "'";
		BigDecimal sumOut = (BigDecimal) JpaUtil.nativeQuery(sqlOut).getSingleResult();
		return (sumIn==null?BigDecimal.ZERO:sumIn).subtract(sumOut==null?BigDecimal.ZERO:sumOut);
	}

	@Override
	@Transactional(readOnly = true)
	public BigDecimal getMaxQuantityByWo(String woBizNo, String woBizLineNo) {
		String sumSql = "SELECT SUM(QUANTITY_) AS QUANTITY_ FROM MB_ERP_INV_FLOW WHERE WO_BIZ_NO_ = '" + woBizNo + "' AND WO_BIZ_LINE_NO_ = '" + woBizLineNo + "'";
		BigDecimal sum = (BigDecimal) JpaUtil.nativeQuery(sumSql).getSingleResult();
		return (sum==null?BigDecimal.ZERO:sum);
	}

	@Override
	@Transactional(readOnly = true)
	public Collection<InvFlowSummaryVo> getExecutedInvFlows(String bizNo, String lineNo, String accessType, String whCode) {
		Linq lin = JpaUtil.linq(InvFlow.class)
				.collect("itemCode", Item.class, "itemCode")
				.equal("originBizNo", bizNo)
				.equal("originBizLineNo", lineNo);
		if(StringUtils.isNotBlank(whCode)){
			lin = lin.equal("whCode", whCode);
		}
		List<InvFlow> flows = lin.list();
				
		Map<String, InvFlowSummaryVo> summaryMap = new HashMap<>();
		for(InvFlow flow : flows){
			String key;
			if(whCode == null){
				key = flow.getLotNo();
			}else{
				key = flow.getLotNo()+flow.getWhCode();
			}
			InvFlowSummaryVo vo = summaryMap.get(key);
			
			if(vo == null){
				vo = new InvFlowSummaryVo();
				vo.setItemCode(flow.getItemCode());
				if(flow.getItem() != null){
					vo.setItemName(flow.getItem().getItemName());
					vo.setItemSpec(flow.getItem().getItemSpec());
				}
				vo.setLotNo(flow.getLotNo());
				if(whCode != null){
					vo.setWhCode(whCode);
				}
				
				vo.setQuantity(BigDecimal.ZERO);
			}
			if(accessType.equals(flow.getAccessType())){
				// 调拨时写入仓库
				if(whCode == null && vo.getWhCode() == null){
					vo.setWhCode(flow.getWhCode());
				}
				vo.setQuantity(vo.getQuantity().add(flow.getQuantity()));
			}else{
				vo.setQuantity(vo.getQuantity().subtract(flow.getQuantity()));
			}
			if(BigDecimal.ZERO.compareTo(vo.getQuantity()) == 0){
				summaryMap.remove(key);
			}else{
				summaryMap.put(key, vo);
			}
		}
		return summaryMap.values();
	}

}
